from uuid import uuid4
import unittest
import copy

from Autotests.BaseTest import BaseManservSOAPTestCase, PartnerAndAccountAutoCreation
from Autotests.Cloud.Clients.BaseSoapClient import WebFault
from Config.RunConfig import RunConfig, Options
from urlparse import urlparse


@PartnerAndAccountAutoCreation
class StorageTests(BaseManservSOAPTestCase):
    def __init__(self, *args, **kwargs):
        BaseManservSOAPTestCase.__init__(self, *args, **kwargs)

    def _getStorageNodeInfo(self, storageInfo, nodeId):
        storageNodes = self.executor.enumerateStorageNodes(storageInfo).storageNodeInfo
        return self._findByField(storageNodes, 'id', nodeId)

    def _findByField(self, sequence, field, value):
        for item in sequence:
            if getattr(item, field) == value:
                return item

    def _addStorage(self, name=str(uuid4())):
        partnerInfo = self.getPartnerForCaseInfo()
        storageId = self.executor.addStorage(name, partnerInfo)
        storages = self.executor.enumerateStorages(partnerInfo).storageInfo
        return self._findByField(storages, 'id', storageId)

    def _addStorageNode(self, storageInfo, name=str(uuid4())):
        storageNodeId = self.executor.addStorageNode(name,
                                                     storageInfo.id,
                                                     RunConfig().get(Options.Soap.defaultUser),
                                                     RunConfig().get(Options.Soap.defaultPassword),
                                                     urlparse(RunConfig().get(Options.Soap.cloudUrl)).hostname,
                                                     'WEBDAVS')
        return self._getStorageNodeInfo(storageInfo, storageNodeId)

    def test_AddStorage(self):
        casePartnerInfo = self.getPartnerForCaseInfo()
        storagesAmount = self.sudsSequenceLen(self.executor.enumerateStorages(casePartnerInfo), 'storageInfo')
        storageInfo = self._addStorage()
        storages = self.executor.enumerateStorages(casePartnerInfo).storageInfo

        self.assertEqual(self.sudsSequenceLen(storages), storagesAmount + 1)
        self.assertInSudsSequence(storageInfo, storages)
        self.assertRaises(WebFault, self._addStorage, storageInfo.name)

        wrongPartnerInfo = copy.copy(casePartnerInfo)
        wrongPartnerInfo.id = 100500
        self.assertRaises(WebFault, self.executor.addStorage, uuid4(), wrongPartnerInfo)

    def test_AddStorageNode(self):
        storageInfo = self._addStorage()
        nodesAmount = self.sudsSequenceLen(self.executor.enumerateStorageNodes(storageInfo), 'storageNodeInfo')

        nodeInfo = self._addStorageNode(storageInfo)
        nodes = self.executor.enumerateStorageNodes(storageInfo).storageNodeInfo

        self.assertEqual(len(nodes), nodesAmount + 1)
        self.assertInSudsSequence(nodeInfo, nodes)
        self.assertRaises(WebFault, self._addStorageNode, storageInfo, nodeInfo.name)

        wrongStorageInfo = copy.copy(storageInfo)
        wrongStorageInfo.id = 100500
        self.assertRaises(WebFault, self._addStorageNode, wrongStorageInfo)

    def test_EnumerateStorageNodes(self):
        storageInfo = self._addStorage()
        nodesAmount = self.sudsSequenceLen(self.executor.enumerateStorageNodes(storageInfo), 'storageNodeInfo')
        nodeInfo = self._addStorageNode(storageInfo)
        nodes = self.executor.enumerateStorageNodes(storageInfo).storageNodeInfo
        self.assertEqual(self.sudsSequenceLen(nodes), nodesAmount + 1)
        self.assertInSudsSequence(nodeInfo, nodes)

    def test_EnumerateStorages(self):
        casePartnerInfo = self.getPartnerForCaseInfo()
        storagesAmount = self.sudsSequenceLen(self.executor.enumerateStorages(casePartnerInfo), 'storageInfo')
        storageInfo = self._addStorage()
        storages = self.executor.enumerateStorages(casePartnerInfo).storageInfo
        self.assertEqual(self.sudsSequenceLen(storages), storagesAmount + 1)
        self.assertInSudsSequence(storageInfo, storages)

    def test_EnumerateStorageStatistics(self):
        storageInfo = self._addStorageNode(self._addStorage())
        partnerInfo = self.getPartnerForCaseInfo()
        statistics = self.executor.enumerateStorageStatistics(partnerInfo).storageStatisticsInfo
        nodeStatistic = self._findByField(statistics, 'locationId', storageInfo.locationId)
        self.assertInSudsSequence(nodeStatistic, statistics)

    def test_EnumerateStorageNodesByAccountId(self):
        nodes = self.executor.enumerateStorageNodesForAccount(self.getAccountForCaseInfo()).accountStorageNodeInfo
        self.assertEqual(self.sudsSequenceLen(nodes), 1)

    def test_UpdateStorageNodeState(self):
        def makeState(state='Online', usedStorage=100, totalStorage=500):
            return dict(state=state, usedStorage=usedStorage, totalStorage=totalStorage)

        storageInfo = self._addStorage()
        nodeInfo = self._addStorageNode(storageInfo)
        newState = makeState()
        self.executor.updateStorageNodeState(nodeInfo.id, **newState)
        nodeInfo = self._getStorageNodeInfo(storageInfo, nodeInfo.id)
        for key in newState.keys():
            self.assertEqual(str(newState[key]), str(getattr(nodeInfo, key)))

        self.assertRaises(WebFault, self.executor.updateStorageNodeState, 100500, **newState)

        wrongStates = [makeState(usedStorage=-200), makeState(totalStorage=-40),
                       makeState(usedStorage=1000, totalStorage=50)]
        for wrongState in wrongStates:
            with self.assertRaises(Exception) as exc:
                self.manserv.GetLocationInfoByName(nodeInfo.id, **wrongState)
            self.assertEqual(exc.exception.message, (502, u'Bad Gateway'))

    def test_UpdateStorageNodeMode(self):
        storageInfo = self._addStorage()
        nodeInfo = self._addStorageNode(storageInfo)

        for mode in ['Undefined', 'Operable', 'OutOfService']:
            nodeMode = dict(mode=mode, message='try: %s' % mode)
            self.executor.updateStorageNodeMode(nodeInfo.id, nodeMode)

        nodeInfo.id = 100500  # make wrong nodeInfo
        self.assertRaises(WebFault, self._getStorageNodeInfo, nodeInfo, nodeMode)
        self.warnings.warn("complete this test")

    def test_UpdateStorageNode(self):
        storageInfo = self._addStorage()
        nodeInfo = self._addStorageNode(storageInfo)
        fieldsForTest = dict(family = "FTP", gatewayHost='127.0.0.1')
        for key in fieldsForTest.keys():
            value = fieldsForTest[key]
            self.executor.updateStorageNode(nodeInfo.id, **{key: value})
            nodeInfo = self._getStorageNodeInfo(storageInfo, nodeInfo.id)
            self.assertEqual(getattr(nodeInfo, key), value)
        wrongNodeId = 100500
        self.assertRaises(WebFault, self.executor.updateStorageNode, wrongNodeId, **fieldsForTest)

if __name__ == "__main__":
    unittest.main()
